package svc.elib.db;

import java.util.LinkedList;
import java.util.StringTokenizer;

/**
 * Information about author
 * 
 * @author svc
 * @date 6.6.2012
 */
public class Author {

	private String name;
	
	private String firstName;
	
	private String lastName;
	
	private boolean male;
	
	/**
	 * true if the author has short name (e.g. "M. Savic")
	 */
	private boolean shortName;
	
	
	/**
	 * list of papers written by author
	 */
	private LinkedList<Paper> papers = new LinkedList<Paper>();
	
	public Author(String name, boolean male) {
		this.name = name;
		this.male = male;
		resolveFirstLastName();
		shortName = isShort(firstName);
	}
	
	public String getName() {
		return name;
	}
	
	public boolean equals(Author another) {
		return name.compareToIgnoreCase(another.name) == 0 &&
			   male == another.male;
	}	
	
	public void addPaper(Paper p) {
		papers.addLast(p);
	}
	
	public LinkedList<Paper> getPapers() {
		return papers;
	}
	
	public int getNumPapers() {
		return papers.size();
	}
	
	public int getNumPapers(int endYear) {
		int cnt = 0;
		for (int i = 0; i < papers.size(); i++) {
			if (papers.get(i).getYear() <= endYear)
				cnt++;
		}
		
		return cnt;
	}
	
	public String getFirstName() {
		return firstName;
	}
	
	public String getLastName() {
		return lastName;
	}
	
	private boolean isShort(String firstName) {
		if (firstName.length() == 0 || firstName.length() == 1)
			return true;
		
		int numDots = 0;
		int numSpaces = 0;
		for (int i = 0; i < firstName.length(); i++) {
			if (firstName.charAt(i) == '.')
				numDots++;
			else
			if (firstName.charAt(i) == ' ')
				numSpaces++;
		}
		
		if (numDots >= (firstName.length() - numSpaces) / 2)
			return true;
		
		return false;
	}
	
	private void resolveFirstLastName() {
		int uIndex = name.indexOf("_");
		lastName = name.substring(0, uIndex);
		firstName = name.substring(uIndex + 1);
	}
	
	public boolean isShortName() {
		return shortName;
	}

	public boolean isMale() {
		return male;
	}
	
	public int getFirstYear() {
		int min = Integer.MAX_VALUE;
		for (int i = 0; i < papers.size(); i++) {
			Paper p = papers.get(i);
			if (p.getYear() < min) {
				min = p.getYear();
			}
		}
		
		return min;
	}
	
	public int getLastYear() {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < papers.size(); i++) {
			Paper p = papers.get(i);
			if (p.getYear() > max) {
				max = p.getYear();
			}
		}
		
		return max;
	}
	
	public int getLastYear(int endYear) {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < papers.size(); i++) {
			Paper p = papers.get(i);
			if (p.getYear() <= endYear && p.getYear() > max) {
				max = p.getYear();
			}
		}
		
		return max;
	}
	
	public int getActivitySpan() {
		return getLastYear() - getFirstYear() + 1;
	}
	
	public String getInfo() {
		String gender = male ? "male" : "female";
		return name + ", " + gender + ", " + getNumPapers() + ", " + getFirstYear() + ", " + getLastYear();
	}
	
	public void printFullInfo() {
		System.out.println("Name = " + name);
		String gender = male ? "male" : "female";
		System.out.println("Gender = " + gender);
		System.out.println("Num publications = " + papers.size());
		System.out.println("First year = " + getFirstYear() + 
				           ", last year = " + getLastYear() + ", activity = " + getActivitySpan());
		System.out.println("Papers: ");
		for (int i = 0; i < papers.size(); i++) {
			System.out.println(papers.get(i).getInfo());
		}
	}

	public String getShortName() {
		if (isShortName())
			return name;
		
		StringTokenizer st = new StringTokenizer(firstName, " ", false);
		StringBuilder shortFirstName = new StringBuilder();
		while (st.hasMoreTokens()) {
			String tok = st.nextToken().trim();
			shortFirstName.append(tok.charAt(0)).append(". ");
		}
		
		String sFn = shortFirstName.toString().trim();
		return lastName + "_" + sFn;
	}

	public boolean isSingle() {
		for (int i = 0; i < papers.size(); i++) {
			if (papers.get(i).getAuthors().size() > 1)
				return false;
		}
		return true;
	}

	
	public Author clone(String journalName) {
		Author a = new Author(this.name, this.male);
		
		for (Paper p : this.papers) {
			if (p.getJournal().compareTo(journalName) == 0) {
				a.addPaper(p);
			}
		}
		
		return a;
	}
}
